﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Qy.Common;
using Qy.Models;
using Qy.Service;
using Qy.Web.Authorize;
using System;
using System.Collections;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace Qy.Web.Api
{
    [Route("Api/[controller]/[action]")]
    [Verify]
    public class UploadController : Base
    {
        private readonly ConfigService configService;
        private readonly AttmentService _attment;
        private readonly LoginUtil _LoginUtil;
        public UploadController(ConfigService config, AttmentService attmentService, LoginUtil LoginUtil)
        {
            configService = config;
            _attment = attmentService;
            _LoginUtil = LoginUtil;
        }

        /// <summary>
        /// 上传
        /// </summary>
        /// <param name="uploadDto"></param>
        /// <returns></returns>
        [HttpPost]
        [ActionPermissionFilter(Permission = PermissionKeys.Upload_Upload)]
        public async Task<IActionResult> Upload([FromForm] UploadDto uploadDto)
        {
            IFormFileCollection files = HttpContext.Request.Form.Files;
            UploadRes uploadRes = new();
            if (files.Count < 1)
            {
                uploadRes.Error = "上传文件不存在！";
                return Json(uploadRes);
            }
            IFormFile file = files[0];

            UploadInfo uploadInfo = new()
            {
                Size = file.Length,       //统计文件大小
                FileName = file.FileName,//原始文件名
                SaveDir = uploadDto.SaveDir,//自定义保存目录
                FileExt = Path.GetExtension(file.FileName),//文件后缀
                UpLoadConfig = await configService.GetByUploadAsync()
            };

            uploadRes = uploadDto.Type == "attment" ? AttmentCheck(uploadInfo) : ImgCheck(uploadInfo);
            if (uploadRes.Error != null) return Json(uploadRes);

            string dateDir = DateTime.Now.ToString("yyyyMM");
            var dirPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", uploadInfo.UpLoadConfig.BaseDir, uploadRes.SaveDir, dateDir);
            if (!Directory.Exists(dirPath)) Directory.CreateDirectory(dirPath);//如目录不存在，则以当前日期创新目录
            string newFileName = MD5Utility.MD5Encrypt16(uploadInfo.FileName + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff:ffffff")).ToLower(); //获取当前时间微秒 生成MD5
            string saveFilePath = Path.Combine(dirPath, newFileName + uploadInfo.FileExt); //当前上传文件应存放的位置 path.combine 内置跨平台文件系统路径拼接方法
            using var stream = System.IO.File.Create(saveFilePath);
            try
            {
                await file.CopyToAsync(stream);
                uploadRes.Success = true;
                uploadRes.Filename = uploadInfo.FileName;
                uploadRes.Ext = uploadInfo.FileExt;
                uploadRes.Url = "/" + uploadInfo.UpLoadConfig.BaseDir + "/" + uploadRes.SaveDir + "/" + dateDir + "/" + newFileName + uploadInfo.FileExt;

                if (uploadDto.Type == "attment")
                {
                    return Json(new { data = uploadRes, status = 1, msg = "成功上传附件", attPkey = await DbPreKeyAsync(uploadInfo, uploadRes.Url) });
                }
                else
                {
                    return Json(new { data = uploadRes, status = 1, msg = "上传成功" });
                }

            }
            catch (Exception ex)
            {
                uploadRes.Success = false;
                uploadRes.Error = ex.ToString();
                return Json(uploadRes);
            }
        }

        /// <summary>
        /// 图片检查
        /// </summary>
        /// <returns></returns>
        private static UploadRes ImgCheck(UploadInfo uploadInfo)
        {
            string[] imgageExts = uploadInfo.UpLoadConfig.ImageExt.Split(',');
            int imageSize = uploadInfo.UpLoadConfig.ImageSize * 1024;
            UploadRes uploadRes = new();
            if (((IList)imgageExts).Contains(uploadInfo.FileExt))
            {
                if (!imgageExts.Any(m => m.Equals(uploadInfo.FileExt, StringComparison.OrdinalIgnoreCase)))
                {
                    uploadRes.Error = "上传图片类型不合法！";
                    return uploadRes;
                }
                if (uploadInfo.Size > imageSize)
                {
                    uploadRes.Error = "上传图片超过系统大小限制！";
                    return uploadRes;
                }
                uploadRes.SaveDir = uploadInfo.SaveDir ?? uploadInfo.UpLoadConfig.ImageDir;
            }
            else
            {
                uploadRes.Error = "非法上传！";
                return uploadRes;
            }
            return uploadRes;
        }
        /// <summary>
        /// 附件检查
        /// </summary>
        /// <returns></returns>
        private static UploadRes AttmentCheck(UploadInfo uploadInfo)
        {
            UploadRes uploadRes = new();
            string[] fileExts = uploadInfo.UpLoadConfig.FileExt.Split(',');
            int fileSize = uploadInfo.UpLoadConfig.FileSize * 1024;

            if (((IList)fileExts).Contains(uploadInfo.FileExt))
            {
                if (!fileExts.Any(m => m.Equals(uploadInfo.FileExt, StringComparison.OrdinalIgnoreCase)))
                {
                    uploadRes.Error = "上传文件类型不合法！";
                    return uploadRes;
                }
                if (uploadInfo.Size > fileSize)
                {
                    uploadRes.Error = "上传文件超过系统大小限制！";
                    return uploadRes;
                }
                uploadRes.SaveDir = uploadInfo.SaveDir ?? uploadInfo.UpLoadConfig.FileDir;
            }
            else
            {
                uploadRes.Error = "非法上传！";
                return uploadRes;
            }
            return uploadRes;
        }
        /// <summary>
        /// 附件上传信息写入数据库
        /// </summary>
        /// <param name="uploadInfo"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        private async Task<object> DbPreKeyAsync(UploadInfo uploadInfo, string url)
        {
            int userId = _LoginUtil.LoginUserId();
            Attment attment = new()
            {
                Filename = uploadInfo.FileName,
                Ext = uploadInfo.FileExt,
                Url = url,
                Size = uploadInfo.Size / 1024,
                Source = uploadInfo.SaveDir,
                Uid = userId,
                Time = DateTime.Now
            };
            return await _attment.InsertAsync(attment);
        }

    }

}
